<template>
  <div class="basic-table" style="width: 100%;" v-adaptive>
    <el-table
      ref="tableRef"
      :rowKey="rowKey"
      :data="tableData"
      :border="border"
      @selection-change="selectionChange"
      @select="select"
      stripe
      v-loading="loading"
      element-loading-text="正在加载中..."
      :header-cell-style="headerSty"
      :height="height"
      :show-summary="isShowSummary"
      :show-header="isShowHeader"
      :summary-method="getSummaries"
      :header-cell-class-name="cellClass"
      :span-method="props.spanMethod"
      :style="tableStyle"
      :cell-style="cellStyle"
      :fit="fit"
      :row-style="rowStyle"
      :isCenter="isCenter"
      style="width: 100%;"
    >
      <!-- 供选择的表格 -->
      <!-- <el-table-column v-if="isDoubleCheck" type="selection" width="55" /> -->
      <el-table-column label="序号" type="index" width="60" v-if="isIndex" />
      <el-table-column type="selection" width="60" v-if="hasSelection" />
      <template v-for="item in tableColumns" :key="item.prop">
        <!-- selection || index -->
        <!-- <el-table-column
          v-if="(item.type == 'selection' || item.type == 'index') && item.status"
          :type="item.type"
          :reserve-selection="item.type == 'selection'"
          :label="item.label"
          :width="item.width"
          :fixed="item.fixed"
        > 
        </el-table-column> -->
        <!-- expand（展开查看详情，请使用作用域插槽） -->
        <el-table-column
          v-if="item.type == 'expand' && item.status"
          :type="item.type"
          :label="item.label"
          :width="item.width"
          :fixed="item.fixed"
          v-slot="scope"
        >
          <slot :name="item.type" :row="scope.row"></slot>
        </el-table-column>
        <!-- other -->
        <el-table-column
          v-if="(!item.type && item.prop) && item.status"
          :prop="item.prop"
          :label="item.label"
          :width="item.width"
          :min-width="item.minWidth"
          :show-overflow-tooltip="item.prop !== 'operation'"
          :resizable="true"
          :fixed="item.fixed"
          :align="item.align"
        >
          <!-- 自定义配置每一列 header 表头插槽 -->
          <template #header="{ column }">
            <slot :name="`${column.property}_header`" :column="column">
              {{ column.label }}</slot
            >
          </template>
          <!-- 自定义配置每一列 slot（使用作用域插槽） -->
          <template #default="scope">
            <slot :name="item.prop" :row="scope.row">
              {{
                (scope.row[item.prop] == null ||
                scope.row[item.prop] == undefined)
                  ? "*"
                  : scope.row[item.prop]
              }}
            </slot>
          </template>
        </el-table-column>
      </template>
      <template #empty>
        <div class="table-empty">
          <!-- <el-empty description="暂无数据" /> -->
          <div>暂无数据</div>
        </div>
      </template>
    </el-table>
  </div>
  <div class="page_box flex_between_start">
    <el-pagination
      v-model:currentPage="currenPage"
      :page-size="option.pageSize"
      :page-sizes="option.pageSizes"
      :background="option.background"
      layout="total, sizes, prev, pager, next, jumper"
      :total="option.total"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      v-if="pagination"
    />
    <el-button 
      type="success" 
      :icon="Refresh" 
      plain 
      @click="refreshTable"
      v-if="pagination"
    >刷新</el-button>
  </div>
</template>

<script setup lang="ts">
import { Refresh } from "@element-plus/icons-vue";
import { ref, watch, computed, onMounted, nextTick, Ref } from "vue";
import { storeToRefs } from "pinia";
import useThemeConfigStore from "@/store/themeConfig";

const themeConfigStore = useThemeConfigStore();
const { getThemeFontSize } = storeToRefs(themeConfigStore);

// 表列接口
interface TableColumns {
  type?: string;
  label: string;
  width?: string | number;
  fixed?: string;
  prop: string;
  value?: string;
  minWidth?: string;
  align?: string;
  status?: boolean
}
// 表格接口，分页
interface ProTableProps<T = any> {
  rowKey?: string;
  tableData: Array<Record<string, any>>;
  tableColumns: Array<TableColumns>;
  pagination?: boolean; // 是否需要分页组件 ==> 非必传（默认为true）
  border?: boolean; // 表格是否显示边框 ==> 非必传（默认为true）
  stripe?: boolean; // 是否带斑马纹表格 ==> 非必传（默认为false）
  childrenName?: string; // 当数据存在 children 时，指定 children key 名字 ==> 非必传（默认为"children"）
  option?: Pagination;
  loading?: boolean;
  isShowSummary?: boolean;
  isShowHeader?: boolean;
  isDoubleCheck?: boolean;
  height?: string;
  isIndex?: boolean;
  hasSelection?: boolean;
  sumProperties?: T[]; // 对哪些字段进行合计计算，当isShowSummary为true的时候，不传就对整个表格中每一个数字项进行计算
  isHeadMultiple?: boolean; // 是否展示多选表格中的头部的全选
  spanMethod?: Function; // 合并表格方法
  summaryMethod?: Function; // 合计计算方法
  isScroll?: boolean; // 是否需要自动滚动
  cellStyle?: Function; // 单元格样式方法
  fit?: boolean; // 列的宽度是否自撑开
  headerSty?: Object | Function; // 表头样式方法
  rowStyle?: Object | Function; // 行样式方法
  tableWidth?: Object // 表格宽度
  isCenter?: boolean; // 是否居中
}
// 分页接口
interface Pagination {
  page: number; // 当前页数，支持 v-model 双向绑定
  pageSize: number; // 每页显示条目个数，支持 v-model 双向绑定/*  */
  total?: number; // 总条目数
  background?: boolean; // 是否为分页按钮添加背景色
  pageSizes?: number[]; // 每页显示条目个数的选择器的选项设置 ==> 非必传(默认[10, 20, 30, 40, 50, 100])
}

// 接受父组件参数，配置默认值
const props = withDefaults(defineProps<ProTableProps>(), {
  rowKey: () => {
    return "id";
  },
  tableData: () => {
    return [];
  },
  tableColumns: () => {
    return [] as Array<TableColumns>;
  },
  pagination: true,
  border: false,
  stripe: false,
  childrenName: "children",
  isShowSummary: false,
  isShowHeader: true,
  isDoubleCheck: false,
  option: () => {
    return {} as Pagination;
  },
  loading: false,
  height: "100%",
  isIndex: true,
  hasSelection: true,
  sumProperties: [] as any,
  isHeadMultiple: true,
  isScroll: false,
  fit: false,
  headerSty: () => {
    return {
      backgroundColor: "#FAFAFB",
      color: "#101011"
    };
  },
  isCenter: false
});

onMounted(() => {
  // 如果需要滚动的话
  if(props.isScroll) {
    scrollUp()
  }
  postDomRef();
});
/**
 * defineEmits emit给父组件
 */
interface EmitEvent {
  (e: "handleCurrentChange", params: any): void;
  (e: "selectionChange", params: any): void;
  (e: "select", params: any): void;
  (e: "handleSizeChange", params: any): void;
  (e: "postDomRef", params: Ref<HTMLElement>): void;
  (e: "refreshTable"): void;
}
const emit = defineEmits<EmitEvent>();
// 当选择项发生变化时会触发该事件
const selectionChange = (val: any) => {
  // console.log('selectionChange')
  emit("selectionChange", val);
};
// 当用户手动勾选数据行的 Checkbox 时触发的事件
const select = (selection: Array<any>) => {
  emit("select", selection);
};

const refreshTable = () => {
  // 通知父组件要刷新啦
  emit("refreshTable");
}

/**
 * 分页操作以下
 */
const currenPage = ref(1); // 当前页
// 分页
watch(
  () => props.option.page,
  (newVal) => {
    currenPage.value = newVal;
  }
);
const handleCurrentChange = (val: number) => {
  emit("handleCurrentChange", val);
  toTop();
};
const handleSizeChange = (val: number) => {
  emit("handleSizeChange", val);
  toTop();
};
const postDomRef = () => {
  emit("postDomRef", tableRef.value);
};
// 回到顶部
const tableRef = ref();
const toTop = () => {
  tableRef.value.setScrollTop(0);
};
const toggleRowSelection = (row: any, selected: any) => {
  console.log("row", row);
  tableRef.value!.toggleRowSelection(row, selected);
  console.log("getSelectionRows()", getSelectionRows());
};
// 获取列表中当前选中的行
const getSelectionRows = () => {
  return tableRef.value!.getSelectionRows();
};
// 清除多选
const clearSelection = () => {
  tableRef.value!.clearSelection();
};
defineExpose({ toggleRowSelection, getSelectionRows, clearSelection });

// const headerSty = computed(() => {
//   return {
//     backgroundColor: "#FAFAFB",
//     color: "#101011",
//   };
// });
const cellClass = (row: any) => {
  if (row.column.type == "selection" && !props.isHeadMultiple) {
    return "disabledCheck";
  }
};
// 关注字体大小
const tableStyle = computed(() => {
  return {
    fontSize: getThemeFontSize.value,
    // width: props.tableWidth || '100%',
    backgroundColor: 'transparent',
    margin: props.isCenter? '0 auto' : '0',
  };
});

// 合计
const getSummaries = (param: any) => {
  const { columns, data } = param;
  const sums: string[] = [];
  columns.forEach((column, index) => {
    // 第一列为关键字合计
    if (index === 0) {
      sums[index] = "合计";
      return;
    }
    // 合计不包含的字段不进行计算
    if (!props.sumProperties.includes(column.property)) {
      sums[index] = "";
      return;
    }
    // 合计包含的字段进行计算
    const values = data.map((item) => Number(item[column.property]));
    if (!values.every((value) => Number.isNaN(value))) {
      // 模板字符串 可跟拼接中文啥的
      sums[index] = `${values.reduce((prev, curr) => {
        const value = Number(curr);
        if (!Number.isNaN(value)) {
          return prev + curr;
        } else {
          return prev;
        }
      }, 0)}`;
    } else {
      // 合计字段是非Number
      sums[index] = "N/A";
    }
  });
  return sums;
};

/** 滚动操作 -- 开始 */
let timer = ref<any>(null)
function scrollUp() {
  nextTick(() => {
    const demo = tableRef.value.$refs.bodyWrapper.getElementsByClassName('el-scrollbar__wrap')[0]
    const tableScroll = ref(true)
    demo.addEventListener('mouseover', () => {
      tableScroll.value = false
    })
    demo.addEventListener('mouseout', () => {
      tableScroll.value = true
    })
    timer.value = setInterval(() => {
      if (tableScroll.value) {
        demo.scrollTop += 1
        if (demo.clientHeight + demo.scrollTop >= demo.scrollHeight - 1.5) {
          demo.scrollTop = 0
        }
      }
    }, 100)
  })
}
/** 滚动操作 -- 结束 */
</script>

<style scoped lang="scss">
.basic-table {
  height: 100%;
  width: 100%;
  // padding-top: 0.7rem;
  // margin-top: 10px;
}
.page_box {
  width: 100%;
  text-align: center;
  padding-top: 20px;
}
:deep(.el-table .disabledCheck .cell .el-checkbox__inner) {
  display: none;
}
</style>
